package com.ansion.basedb.dao.helper;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteTransactionListener;

import com.ansion.basedb.database.DatabaseTools;
import com.ansion.basedb.database.ISqlDataBase;
import com.ansion.basedb.database.TrackHelper;
import com.ansion.basedb.database.sql.SQLTable;
import com.ansion.log.VLog;
import com.ansion.utils.ContactUtil;
import com.ansion.utils.ResourceUtils;
import com.ansion.utils.SharedPref;

import java.util.List;

public class AppDatabaseHelper extends SQLiteOpenHelper implements ISqlDataBase {
    public static final String kNEXT_ROWID_RANGEBEGIN = "kNEXT_ROWID_RANGEBEGIN";
    private static long m_nextrowidlimit;
    private static long m_currrowid;
    private Context context;
    private String dbName;
    private int version;
    private List<Class<?>> models;
    private List<SQLTable> tables;

    public AppDatabaseHelper(Context context, String name, CursorFactory factory, int version, List<Class<?>> models, List<SQLTable> tables) {
        super(context, name, factory, version);
        this.context = context;
        this.dbName = name;
        this.version = version;
        this.models = models;
        this.tables = tables;
    }

    public static long getNextRowId() {
        SharedPref sp = SharedPref.getInstance();
        synchronized (AppDatabaseHelper.class) {
            if (m_currrowid <= 0) {
                initRowId();
            }
            long rowId = m_currrowid;
            m_currrowid++;
            if (m_currrowid >= m_nextrowidlimit) {
                m_nextrowidlimit += 10000;
                sp.putLong(kNEXT_ROWID_RANGEBEGIN,
                        m_nextrowidlimit);
            }
            return rowId;
        }
    }

    public static void initRowId() {
        SharedPref sp = SharedPref.getInstance(ResourceUtils.getContext());
        m_nextrowidlimit = sp.getLong(kNEXT_ROWID_RANGEBEGIN, 0);
        m_currrowid = m_nextrowidlimit + 1;
        m_nextrowidlimit += 10000;
        sp.putLong(kNEXT_ROWID_RANGEBEGIN, m_nextrowidlimit);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        if (tables != null && tables.size() > 0) {
            SqlTableHelper.createTable(db, tables, version);
        }
        _onCreate(db);
    }

    private void _onCreate(SQLiteDatabase db) {
        if (models != null && models.size() > 0) {
            for (Class<?> claz : models) {
                DatabaseTools.onCreate(db, claz);
            }
            if (dbName.contains("_coco")) {
                //fix no sessionId index of ChatMessageModel and GroupMessageModel
//                db.execSQL("CREATE INDEX IF NOT EXISTS index_sessionid_GroupMessageModel on GroupMessageModel(sessionid);");

            }
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (newVersion > oldVersion) {
//			DatabaseTools.onUpgrade(db, dbName, context, User.class);
            if (models != null && models.size() > 0) {
                for (Class<?> claz : models) {
                    DatabaseTools.onUpgrade(db, dbName, context, claz);
                }
            }
            _onCreate(db);
        }
        if (tables != null && tables.size() > 0) {
            SqlTableHelper.upgradeTable(db, tables, oldVersion, newVersion);
        }
    }

    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        String message = "AppDatabaseHelper.onDowngrade: old:" + oldVersion + " new:" + newVersion;
        VLog.FileLog.e("TAG_DB_SQLITE", message);
        TrackHelper.trackError("db", "db_downgrade", message, ContactUtil.getMyUid());
    }

    @Override
    public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
        getWritableDatabase().beginTransactionWithListener(transactionListener);
    }

    @Override
    public void setTransactionSuccessful() {
        getWritableDatabase().setTransactionSuccessful();
    }

    @Override
    public void endTransaction() {
        getWritableDatabase().endTransaction();
    }

    @Override
    public Cursor rawQuery(String sql) {
        return getReadableDatabase().rawQuery(sql, null);
    }

    @Override
    public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
        return getWritableDatabase().update(table, values, whereClause, whereArgs);
    }

    @Override
    public void execSQL(String sql, Object[] bindArgs) throws SQLException {
        if (bindArgs == null) {
            getWritableDatabase().execSQL(sql);
        } else {
            getWritableDatabase().execSQL(sql, bindArgs);
        }

    }

    @Override
    public int delete(String table, String whereClause, String[] whereArgs) {
        return getWritableDatabase().delete(table, whereClause, whereArgs);
    }

    @Override
    public long replace(String table, String nullColumnHack, ContentValues initialValues) {
        return getWritableDatabase().replace(table, nullColumnHack, initialValues);
    }

    @Override
    public long insert(String table, String nullColumnHack, ContentValues values) {
        return getWritableDatabase().insert(table, nullColumnHack, values);
    }
}
